package solution.liuyu2783.sort;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 快速排序
 * 第一步，选择一个值作为基准值；
 * 第二步，找到基准值的位置，并将小于基准值的元素放在基准值的前面，大于基准值的元素放在基准值的后面；
 * 第三步，对基准值的左右两侧递归地进行这个过程。
 *
 * Q: 为啥扫描顺序是先从右到左，再从左到右?
 * A: 因为我们选择第一个值做为基准值以后，我们可以当做基准值的位置是空出来了。需要将后面一个小于基准值的值放过来，我们才先从后向前扫描。
 */
public class QuickSortDemo {

    public static final Integer[] data ={4,1,5,9,2,6,7,3,8,2,5};
    static int i = 0;
    public static void quickSort(Integer[] arr, int left, int right){
        //如果left等于right，即数组只有一个元素，直接返回
        if(left >= right){
            return;
        }
        //设置基准值
        int key = arr[left];
        //数组中比key小的放在左边，比key大的放在右边，key值下标为i
        int x = left;
        int y = right;
        while (x < y){
            //y从右向左, 直到找到小于key的值
            while(arr[y] > key && x <y){
                y--;
            }
            //x从左向右, 直到找到大于key的值
            while(arr[x] <= key && x <y){
                x++;
            }
            //交换x y的值
            if(x < y){
                int temp = arr[x];
                arr[x] = arr[y];
                arr[y] = temp;
            }
        }
        // 将基准数放到中间的位置（基准数归位）
        arr[left] = arr[x];
        arr[x] = key;

        List<String> collect = Arrays.stream(data).map(d -> d.toString()).collect(Collectors.toList());
        System.out.println((i++) + "==== " + collect);
        // 递归，继续向基准的左右两边执行和上面同样的操作
        quickSort(arr, left, x - 1);
        quickSort(arr, x+1, right);
    }

    public static void main(String[] args) {
        quickSort(data, 0, data.length-1);
        List<String> collect = Arrays.stream(data).map(x -> x.toString()).collect(Collectors.toList());
        System.out.println(collect);
    }

}
